package com.liqw.core;

import lombok.extern.slf4j.Slf4j;
import org.openqa.selenium.By;
import org.openqa.selenium.JavascriptExecutor;
import org.openqa.selenium.WebDriver;
import org.openqa.selenium.WebElement;

import java.util.Set;
import java.util.StringJoiner;
import java.util.concurrent.Callable;
import java.util.concurrent.Semaphore;
import java.util.concurrent.TimeUnit;
import java.util.concurrent.atomic.AtomicBoolean;
import java.util.concurrent.atomic.AtomicReference;
import java.util.concurrent.locks.ReentrantLock;

/**
 * 课程观看任务（实现Callable接口）
 */
@Slf4j
class LiveCourseTask implements Callable<Boolean> {
    // 移除静态锁，改为直接锁定WebDriver实例
    private final WebDriver courseDriver;
    private final WebElement courseItem;
    private final Semaphore semaphore;
    private final AtomicReference<String> mainWindowHandleRef;
    private final LiveCourseManager liveCourseManager;

    private String currentWindowHandle;
    private WebElement videoPlayer;

    public LiveCourseTask(WebDriver courseDriver,
                          WebElement courseItem,
                          Semaphore semaphore,
                          AtomicReference<String> mainWindowHandleRef,
                          LiveCourseManager liveCourseManager
    ) {
        this.courseItem = courseItem;
        this.courseDriver = courseDriver;
        this.semaphore = semaphore;
        this.mainWindowHandleRef = mainWindowHandleRef;
        this.liveCourseManager = liveCourseManager;
    }

    @Override
    public Boolean call() {
        String courseName = liveCourseManager.getCourseTitle(courseItem);
        boolean result = false;

        try {
            // 获取信号量许可
            semaphore.acquire();
            log.info("开始处理课程: {}", courseName);
            
            try {
                // 使用synchronized直接锁定WebDriver对象
                synchronized (courseDriver) {
                    // 确保在主窗口操作
                    courseDriver.switchTo().window(mainWindowHandleRef.get());
                    if (currentWindowHandle == null || videoPlayer == null) {
                        log.info("获取WebDriver锁成功，开始播放课程: {}", courseName);

                        // 等待新窗口打开并切换（使用正确的方法）
                        Set<String> originalHandles = courseDriver.getWindowHandles();
                        // 查找播放按钮
                        WebElement playButton1 = liveCourseManager.findPlayButton(courseItem);
                        if (playButton1 == null) {
                            log.error("未找到播放按钮");
                            return false;
                        }

                        // 点击播放按钮并打开新窗口
                        boolean clickSuccess1 = WebDriverUtils.clickElement(courseDriver, playButton1);
                        if (!clickSuccess1) {
                            log.error("点击播放按钮失败");
                            return false;
                        }

                        currentWindowHandle = WebDriverUtils.switchToNewWindow(originalHandles, courseDriver);
                        if (currentWindowHandle == null) {
                            log.error("新窗口未打开");
                            return false;
                        }

                        WebDriverUtils.waitForElementVisible(courseDriver, By.xpath(SelectorConstants.XPATH_LIVE_COURSE_PLAY_BUTTON));
                        // 点击播放按钮
                        WebElement playButton = courseItem.findElement(By.xpath(SelectorConstants.XPATH_LIVE_COURSE_PLAY_BUTTON));
                        if (playButton != null) {
                            log.info("找到播放按钮，准备点击");
                            boolean clickSuccess = WebDriverUtils.clickElement(courseDriver, playButton);

                            if (clickSuccess) {
                                log.info("播放按钮点击成功，等待视频加载");

                                // 等待视频播放器加载
                                videoPlayer = WebDriverUtils.waitForElementVisible(
                                        courseDriver, By.cssSelector(SelectorConstants.LIVE_VIDEO_PLAYER));

                                if (videoPlayer != null) {
                                    log.info("视频播放器已加载，开始播放视频");

                                    // 播放视频
                                    Boolean played = playVideo(courseDriver);

                                    // 开始视频观看逻辑（这里先不释放锁，在watchVideo方法中根据进度释放）
                                    result = watchVideoWithLock(courseDriver, courseName, videoPlayer);
                                } else {
                                    log.error("未找到视频播放器");
                                }
                            } else {
                                log.error("播放按钮点击失败");
                            }
                        } else {
                            log.error("未找到播放按钮");
                        }
                    } else {
                        // 开始视频观看逻辑（这里先不释放锁，在watchVideo方法中根据进度释放）
                        result = watchVideoWithLock(courseDriver, courseName, videoPlayer);
                    }
                }
            } catch (Exception e) {
                log.error("播放课程时发生异常", e);
            }
        } catch (Exception e) {
            log.error("处理课程 {} 时发生异常", courseName, e);
            // 确保异常情况下也释放信号量
            semaphore.release();
        } finally {
            try {
                // 清理资源
                WebDriverUtils.closeWindowAndSwitchBack(courseDriver, currentWindowHandle, mainWindowHandleRef.get());
            } catch (Exception e) {
                log.warn("关闭窗口时发生异常: {}", e.getMessage());
            }
            log.info("完成处理课程: {}", courseName);
        }
        return result;
    }

    /**
     * 带锁管理的视频观看方法
     */
    private boolean watchVideoWithLock(WebDriver driver, String courseName, WebElement videoPlayer) throws InterruptedException {
        log.info("开始观看视频: {}", courseName);

        // 获取视频总长度，最多尝试5次
        Double videoDuration = null;
        for (int attempt = 0; attempt < 5 && videoDuration == null; attempt++) {
            videoDuration = getVideoDuration(driver);
            if (videoDuration == null) {
                Thread.sleep(2000);
            }
        }

        // 计算观看时长（总长度的98%或默认30分钟）
        int targetMinutes = 30; // 默认30分钟
        if (videoDuration != null && videoDuration > 0) {
            targetMinutes = (int) (videoDuration * 0.98 / 60);
            if (targetMinutes < 5) {
                targetMinutes = 5; // 最少观看5分钟
            }
            if (targetMinutes > 120) {
                targetMinutes = 120; // 最多观看2小时
            }
        }

        log.info("目标观看时长: {} 分钟", targetMinutes);
        int maxCheckIntervals = targetMinutes * 2; // 每30秒检查一次
        long startTime = System.currentTimeMillis();

        for (int i = 0; i < maxCheckIntervals; i++) {
            try {
                // 每30秒检查一次
                Thread.sleep(30000);

                // 检查视频播放状态并在暂停时恢复播放
                checkAndResumeVideoPlayback(driver, videoPlayer);

                // 计算已观看时间
                int watchedSeconds = (i + 1) * 30;
                int hours = watchedSeconds / 3600;
                int minutes = (watchedSeconds % 3600) / 60;
                int seconds = watchedSeconds % 60;
                String timeFormatted = hours > 0 ?
                        String.format("%02d:%02d:%02d", hours, minutes, seconds) :
                        String.format("%02d:%02d", minutes, seconds);

                // 尝试获取实际播放进度
                Double progress = getVideoProgress(driver);
                if (progress != null) {
                    log.info("课程 {} 已观看 {}, 当前进度: {:.1f}%", courseName, timeFormatted, progress);
                    
                    // 关键修改：在视频进度>0时释放WebDriver锁
                    if (progress > 0 && System.currentTimeMillis() -startTime > TimeUnit.MINUTES.toMillis(1)) {
                        driver.notifyAll(); // 通知可能在等待的其他线程
                        log.info("视频已开始播放，释放WebDriver锁，允许其他任务继续执行");
                    }
                    
                    // 如果进度达到98%，提前结束
                    if (progress >= 98.0) {
                        log.info("课程 {} 进度已达到98%，提前结束观看", courseName);
                        return true;
                    }
                } else {
                    log.info("课程 {} 已观看 {}", courseName, timeFormatted);
                }

                // 检查是否达到目标观看时间
                if (i >= targetMinutes * 2 - 1) {
                    log.info("课程 {} 已达到目标观看时长", courseName);
                    return true;
                }

            } catch (InterruptedException e) {
                Thread.currentThread().interrupt();
                return false;
            }
        }

        log.info("课程 {} 观看完成", courseName);
        return true;
    }

    /**
     * 播放视频
     */
    private Boolean playVideo(WebDriver driver) {
        StringJoiner playScriptJoiner = new StringJoiner("\n");
        playScriptJoiner.add("try {");
        playScriptJoiner.add("  // 尝试直接播放视频");
        playScriptJoiner.add("  var videos = document.querySelectorAll('video');");
        playScriptJoiner.add("  var played = false;");
        playScriptJoiner.add("  ");
        playScriptJoiner.add("  // 尝试播放所有找到的video元素");
        playScriptJoiner.add("  for (var i = 0; i < videos.length; i++) {");
        playScriptJoiner.add("    var video = videos[i];");
        playScriptJoiner.add("    try {");
        playScriptJoiner.add("      video.play();");
        playScriptJoiner.add("      played = true;");
        playScriptJoiner.add("      break;");
        playScriptJoiner.add("    } catch (e) {");
        playScriptJoiner.add("      console.warn('播放video元素失败');");
        playScriptJoiner.add("    }");
        playScriptJoiner.add("  }");
        playScriptJoiner.add("  return played;");
        playScriptJoiner.add("}");
        playScriptJoiner.add("catch(e) {");
        playScriptJoiner.add("  console.error('播放脚本执行失败');");
        playScriptJoiner.add("  return false;");
        playScriptJoiner.add("}");

        return (Boolean) ((JavascriptExecutor) driver).executeScript(playScriptJoiner.toString());
    }


    /**
     * 获取视频总长度（秒）（与原实现相同）
     */
    private Double getVideoDuration(WebDriver driver) {
        try {
            StringJoiner scriptJoiner = new StringJoiner("\n");
            scriptJoiner.add("try {");
            scriptJoiner.add("  var videos = document.querySelectorAll('video');");
            scriptJoiner.add("  for (var i = 0; i < videos.length; i++) {");
            scriptJoiner.add("    var video = videos[i];");
            scriptJoiner.add("    if (video.duration > 0) {");
            scriptJoiner.add("      return video.duration;");
            scriptJoiner.add("    }");
            scriptJoiner.add("  }");
            scriptJoiner.add("  return null;");
            scriptJoiner.add("}");
            scriptJoiner.add("catch(e) {");
            scriptJoiner.add("  return null;");
            scriptJoiner.add("}");

            return (Double) ((JavascriptExecutor) driver).executeScript(scriptJoiner.toString());
        } catch (Exception e) {
            return null;
        }
    }

    /**
     * 获取视频进度（与原实现相同）
     */
    private Double getVideoProgress(WebDriver driver) {
        try {
            StringJoiner scriptJoiner = new StringJoiner("\n");
            scriptJoiner.add("try {");
            scriptJoiner.add("  var videos = document.querySelectorAll('video');");
            scriptJoiner.add("  for (var i = 0; i < videos.length; i++) {");
            scriptJoiner.add("    var video = videos[i];");
            scriptJoiner.add("    if (video.duration > 0 && !isNaN(video.currentTime)) {");
            scriptJoiner.add("      return (video.currentTime / video.duration) * 100;");
            scriptJoiner.add("    }");
            scriptJoiner.add("  }");
            scriptJoiner.add("  return null;");
            scriptJoiner.add("}");
            scriptJoiner.add("catch(e) {");
            scriptJoiner.add("  return null;");
            scriptJoiner.add("}");

            return (Double) ((JavascriptExecutor) driver).executeScript(scriptJoiner.toString());
        } catch (Exception e) {
            return null;
        }
    }

    /**
     * 检查并恢复视频播放状态（与原实现相同）
     */
    private void checkAndResumeVideoPlayback(WebDriver driver, WebElement videoPlayer) {
        try {
            StringJoiner scriptJoiner = new StringJoiner("\n");
            scriptJoiner.add("try {");
            scriptJoiner.add("  var videos = document.querySelectorAll('video');");
            scriptJoiner.add("  var wasPaused = false;");
            scriptJoiner.add("  ");
            scriptJoiner.add("  for (var i = 0; i < videos.length; i++) {");
            scriptJoiner.add("    var video = videos[i];");
            scriptJoiner.add("    if (video.paused && video.currentTime > 0 && !isNaN(video.duration) && video.currentTime < video.duration - 1) {");
            scriptJoiner.add("      video.play();");
            scriptJoiner.add("      wasPaused = true;");
            scriptJoiner.add("    }");
            scriptJoiner.add("  }");
            scriptJoiner.add("  return wasPaused;");
            scriptJoiner.add("}");
            scriptJoiner.add("catch(e) {");
            scriptJoiner.add("  return false;");
            scriptJoiner.add("}");

            Boolean wasPaused = (Boolean) ((JavascriptExecutor) driver).executeScript(scriptJoiner.toString());

            if (wasPaused != null && wasPaused) {
                log.info("检测到视频暂停，已自动恢复播放");
            }
        } catch (Exception e) {
            log.warn("检查和恢复视频播放状态时发生异常", e);
        }
    }
}